"""
监控统计服务层
处理监控面板的数据统计和查询
"""
from sqlalchemy.orm import Session
from sqlalchemy import func, and_
from datetime import datetime, timedelta
from typing import Dict, List, Any

from models.workflow_instance import WorkflowInstance


class MonitoringService:
    """监控服务"""

    @staticmethod
    def get_statistics(db: Session, days: int = 7) -> Dict[str, Any]:
        """
        获取监控统计数据

        Args:
            db: 数据库会话
            days: 统计天数（默认7天）

        Returns:
            统计数据字典
        """
        # 获取当前时间和今天的开始时间
        now = datetime.now()
        today_start = datetime(now.year, now.month, now.day, 0, 0, 0)

        # 1. 统计正在运行的工作流数量
        running_workflows = db.query(WorkflowInstance).filter(
            WorkflowInstance.status.in_(['运行中', '等待中'])
        ).count()

        # 2. 统计今日成功/失败的工作流数量
        today_success = db.query(WorkflowInstance).filter(
            and_(
                WorkflowInstance.status == '已完成',
                WorkflowInstance.finished_at >= today_start
            )
        ).count()

        today_failed = db.query(WorkflowInstance).filter(
            and_(
                WorkflowInstance.status.in_(['失败', '已取消']),
                WorkflowInstance.finished_at >= today_start
            )
        ).count()

        # 3. 计算整体成功率
        total_completed = db.query(WorkflowInstance).filter(
            WorkflowInstance.status.in_(['已完成', '失败', '已取消'])
        ).count()

        success_rate = 0.0
        if total_completed > 0:
            total_success = db.query(WorkflowInstance).filter(
                WorkflowInstance.status == '已完成'
            ).count()
            success_rate = round(total_success / total_completed, 4)

        # 4. 统计最近N天的趋势数据
        trend = []
        for i in range(days - 1, -1, -1):
            date = now - timedelta(days=i)
            date_start = datetime(date.year, date.month, date.day, 0, 0, 0)
            date_end = date_start + timedelta(days=1)

            success_count = db.query(WorkflowInstance).filter(
                and_(
                    WorkflowInstance.status == '已完成',
                    WorkflowInstance.finished_at >= date_start,
                    WorkflowInstance.finished_at < date_end
                )
            ).count()

            failed_count = db.query(WorkflowInstance).filter(
                and_(
                    WorkflowInstance.status.in_(['失败', '已取消']),
                    WorkflowInstance.finished_at >= date_start,
                    WorkflowInstance.finished_at < date_end
                )
            ).count()

            trend.append({
                "date": date.strftime("%Y-%m-%d"),
                "success": success_count,
                "failed": failed_count
            })

        return {
            "running_workflows": running_workflows,
            "today_success": today_success,
            "today_failed": today_failed,
            "success_rate": success_rate,
            "trend": trend
        }

    @staticmethod
    def get_recent_instances(
        db: Session,
        limit: int = 20,
        status: str = None
    ) -> List[WorkflowInstance]:
        """
        获取最近的工作流实例

        Args:
            db: 数据库会话
            limit: 返回数量限制
            status: 状态筛选（可选）

        Returns:
            工作流实例列表
        """
        query = db.query(WorkflowInstance)

        if status:
            query = query.filter(WorkflowInstance.status == status)

        instances = query.order_by(
            WorkflowInstance.created_at.desc()
        ).limit(limit).all()

        return instances

    @staticmethod
    def get_workflow_status_distribution(db: Session) -> Dict[str, int]:
        """
        获取工作流状态分布

        Args:
            db: 数据库会话

        Returns:
            状态分布字典
        """
        # 按状态分组统计
        result = db.query(
            WorkflowInstance.status,
            func.count(WorkflowInstance.id).label('count')
        ).group_by(WorkflowInstance.status).all()

        distribution = {}
        for status, count in result:
            distribution[status] = count

        return distribution

    @staticmethod
    def get_average_duration(db: Session) -> Dict[str, Any]:
        """
        获取平均执行时长统计

        Args:
            db: 数据库会话

        Returns:
            时长统计数据
        """
        # 查询已完成的工作流实例
        completed_instances = db.query(WorkflowInstance).filter(
            and_(
                WorkflowInstance.status == '已完成',
                WorkflowInstance.duration.isnot(None)
            )
        ).all()

        if not completed_instances:
            return {
                "average_duration": 0,
                "min_duration": 0,
                "max_duration": 0,
                "total_count": 0
            }

        durations = [inst.duration for inst in completed_instances]

        return {
            "average_duration": round(sum(durations) / len(durations), 2),
            "min_duration": min(durations),
            "max_duration": max(durations),
            "total_count": len(durations)
        }

    @staticmethod
    def get_top_workflows(db: Session, limit: int = 10) -> List[Dict[str, Any]]:
        """
        获取执行次数最多的工作流

        Args:
            db: 数据库会话
            limit: 返回数量限制

        Returns:
            工作流统计列表
        """
        # 按 workflow_id 分组统计
        result = db.query(
            WorkflowInstance.workflow_id,
            func.count(WorkflowInstance.id).label('execution_count'),
            func.sum(
                func.case(
                    (WorkflowInstance.status == '已完成', 1),
                    else_=0
                )
            ).label('success_count')
        ).filter(
            WorkflowInstance.workflow_id.isnot(None)
        ).group_by(
            WorkflowInstance.workflow_id
        ).order_by(
            func.count(WorkflowInstance.id).desc()
        ).limit(limit).all()

        top_workflows = []
        for workflow_id, execution_count, success_count in result:
            success_rate = 0.0
            if execution_count > 0:
                success_rate = round((success_count or 0) / execution_count, 4)

            top_workflows.append({
                "workflow_id": workflow_id,
                "execution_count": execution_count,
                "success_count": success_count or 0,
                "success_rate": success_rate
            })

        return top_workflows
